﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;
using ElisaHippo.Properties;

namespace ElisaHippo
{
    /// <summary>
    /// Interaction logic for RecipeConfig.xaml
    /// </summary>
    public partial class RecipeConfig : Window
    {
        MannualInput mannualForm;
        ObservableCollection<Recipe> recipes = new ObservableCollection<Recipe>();
        ExperimentGroups allGroups = new ExperimentGroups();
        List<int> allowedCombination = new List<int>();
        ObservableCollection<Brushes> brushes = new ObservableCollection<Brushes>();
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        //ObservableList<>
        public RecipeConfig()
        {
            log.Info("RecipeConfig constructor");
            try
            {
                InitializeComponent();
                ReadGroups();
                InitRecipes();
            }
            catch (Exception ex)
            {
                log.Error(ex.InnerException.Message);
                log.Error("Error happened in RecipeConfig constructor." + ex.Message);
            }
            this.Loaded += new RoutedEventHandler(RecipeConfig_Loaded);
            
        }

        private void InitRecipes()
        {
            log.Info("Initialize recipes");
            string s = "";
            string xmlPath = Utility.GetExeFolder() + "\\TodayTests.xml";
            if (!File.Exists(xmlPath))
                return;

            using (StreamReader sr = new StreamReader(xmlPath))
            {
                s = sr.ReadToEnd();
            }
            recipes = Utility.Deserialize<ObservableCollection<Recipe>>(s);
        }

        public string GetXMLAsString(XmlDocument myxml)
        {
            StringWriter sw = new StringWriter();
            XmlTextWriter tx = new XmlTextWriter(sw);
            myxml.WriteTo(tx);
            string str = sw.ToString();// 
            return str;
        }

        
        private void ReadGroups()
        {
            //throw new NotImplementedException();
            log.Info("Read Groups from configure.");
            string s = Utility.GetDataFolder();
            string sRecipeFolder = s + stringRes.groupFolder;
            IEnumerable<string> allRecipeFiles = Directory.EnumerateFiles(sRecipeFolder,"*.txt");
            
            foreach (string sFile in allRecipeFiles)
            {
                //Debug.WriteLine(sFile);
                using (StreamReader sr = new StreamReader(sFile))
                {
                    string sTest = "";
                    ObservableCollection<string> allowedTests = new ObservableCollection<string>();
                    int slashIndex = sFile.LastIndexOf("\\");
                    string shortName = sFile.Substring(slashIndex+1);
                    shortName = shortName.Substring(0, shortName.Length - 4);
                    Debug.WriteLine(shortName);
                    while ((sTest = sr.ReadLine()) != null)
                    {
                        allowedTests.Add(sTest);

                    }
                    allGroups.Add(new ExperimentGroup(shortName,allowedTests,false));
                }
            }

            //read allowed combination
            //string sAllowedCombination = sRecipeFolder + "允许组合.cfg";
            
            //using (StreamReader sr = new StreamReader(sAllowedCombination))
            //{
            //    string sTest = "";
            //    while ((sTest = sr.ReadLine()) != null)
            //    {
            //        sTest = sTest.ToLower();
            //        if( sTest.StartsWith("0x"))
            //            sTest = sTest.Substring(2);
            //        allowedCombination.Add(int.Parse(sTest,System.Globalization.NumberStyles.HexNumber));
            //    }
            //}
            //ExplainCombination();
        }
        private string GetSupportedCombination()
        {
            string allSupports = "";
            foreach (int i in allowedCombination)
            {
                bool bFirst = true;
                string thisSupport = "[";
                BitArray b = new BitArray(new int[] { i });
                bool[] bits = new bool[b.Count];
                b.CopyTo(bits, 0);
                for (int t = 0; t < bits.Length; t++)
                {
                    if (bits[t])
                    {
                        if (bFirst)
                        {
                            thisSupport += allGroups[t].Name;
                            bFirst = false;
                        }
                        else
                        {
                            thisSupport += "," + allGroups[t].Name;
                        }
                    }
                }
                thisSupport += "]\r\n";
                allSupports += thisSupport;
            }
            return allSupports;
        }
        private void ExplainCombination()
        {
            if (allowedCombination.Count == 0)
                throw new Exception("没有允许的组合！");

            
            SetInfo("支持以下组合：\r\n" + GetSupportedCombination(), Colors.Green);
        }


        void RecipeConfig_Loaded(object sender, RoutedEventArgs e)
        {
            this.Width = 891;
            this.Height = 816;
            lstTestGroup.DataContext = allGroups;
            lstRecipe.DataContext = recipes;
            if (recipes.Count > 0)
                lstRecipe.SelectedIndex = 0;
            
        }

   
        private void UpdateSeletedGroups()
        {
            if (lstRecipe.SelectedIndex == -1)
                return;

            ObservableCollection<string> selGroups = recipes[lstRecipe.SelectedIndex].SelectedGroups;
            for (int i = 0; i < allGroups.Count; i++)
            {
                string group = allGroups[i].Name;

                bool groupSelected = selGroups.IndexOf(group) != -1;
                allGroups[i].IsSelected = groupSelected;
                
            }
            
        }
        
        private void btnColor_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog(); 
            colorDialog.AllowFullOpen = true; 
            colorDialog.ShowDialog(); 
            System.Windows.Media.Color color = new System.Windows.Media.Color();
            color.A = colorDialog.Color.A; 
            color.B = colorDialog.Color.B; 
            color.G = colorDialog.Color.G; 
            color.R = colorDialog.Color.R;
            btnColor.Background = new SolidColorBrush(color);
        }

        

        private void btnDel_Click(object sender, RoutedEventArgs e)
        {

            if (recipes.Count == 0)
            {
                return;
            }
            if (lstRecipe.SelectedItem == null)
            {
                 lstRecipe.SelectedIndex = lstRecipe.Items.Count - 1;
            }
            
            recipes.RemoveAt(lstRecipe.SelectedIndex);
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            log.Info("Add");
            string sRecipeNamePrefix = "新测试";
            int index = 1;
            string sRecipeName; 
            
            //找到一个不重名的测试名
            bool bValidName = true;
            while(true)
            {
                
                sRecipeName = sRecipeNamePrefix + index.ToString();
                bValidName = true;
                for (int i = 0; i < recipes.Count; i++)
                {
                    if (recipes[i].Name == sRecipeName)
                    {
                        bValidName = false;
                        break;
                    }
                }

                if(bValidName)
                    break;
                index++;
            } 
            
            ObservableCollection<string> selGroups = new ObservableCollection<string>();
            selGroups.Add(allGroups[0].Name);
            recipes.Add(new Recipe(Color.FromArgb(255, 0, 200, 50), sRecipeName, selGroups));

            lstRecipe.SelectedIndex = lstRecipe.Items.Count - 1;

        }

        public void GoNextDirectly()
        {
            mannualForm = new MannualInput();
            mannualForm.Recipes = recipes;
            mannualForm.GroupsInfo = allGroups;
            mannualForm.RegisterGroupsForRecipe();
            mannualForm.Closed += new EventHandler(mannualForm_Closed);
            mannualForm.Show();
        }
        private void btnNext_Click(object sender, RoutedEventArgs e)
        {
            log.Info("button Next clicked.");
            bool bValid = true;
            int index1, index2;
            index1 = 0;
            index2 = 0;
            for (int i = 0; i < recipes.Count; i++)
            {
                string s = recipes[i].Name;
                for (int j = 0; j < i; j++)
                {
                    if (s == recipes[j].Name)
                    {
                        index1 = i;
                        index2 = j;
                        bValid = false;
                        break;
                    }
                }
            }
            
            if (!bValid)
            {

                SetInfo(string.Format("今日实验中第{0}与第{1}名字相同,都是\"{2}\"，请调整。", index1 + 1, index2 + 1, recipes[index1].Name), Colors.Red);
                return;
            }
            else
                SetInfo("", Colors.Black);

            for (int i = 0; i < allGroups.Count; i++)
            {
                bool bSelSomeItem = false;
                for (int j = 0; j < allGroups[i].AllowedTests.Count; j++)
                {
                    if (allGroups[i].AllowedTests[j].IsSelected)
                    {
                        bSelSomeItem = true;
                        break;
                    }
                }
                if (!bSelSomeItem)
                {
                    SetInfo(string.Format("实验组{0}没有选择任何项目。", i + 1), Colors.Red);
                    return;
                }
            }

            //检查是否有今日实验
            if (recipes.Count == 0)
            {
                SetInfo("今日实验不可为空！", Colors.Red);
                return;
            }


            //检查今日实验中是否有空项，如果有，提醒用户
            
            Recipe emptyRecipe = null;
            foreach (Recipe recipe in recipes)
            {
                if (recipe.SelectedGroups.Count == 0)
                {
                    emptyRecipe = recipe;
                    break;
                }
            }

            if (emptyRecipe != null)
            {
                string sMessage = string.Format("Recipe:'{0}'所选的组为空，请确认这是你想要设置的吗？\r\n如果你想重新设置，请按‘No’按钮。",emptyRecipe.Name);
                MessageBoxResult res = System.Windows.MessageBox.Show(sMessage, "提醒", MessageBoxButton.YesNo);
                if (res == MessageBoxResult.No)
                    return;
            }
            //string errMsg;
            //bValid = CheckCombinations(out errMsg);
            //if (!bValid)
            //{
            //    SetInfo(errMsg + "\r\n符合条件的组合为：\r\n" + GetSupportedCombination(), Colors.Red);
            //    return;
            //}

            SaveSettings();
            this.Hide();

            mannualForm = new MannualInput();
            mannualForm.Recipes = recipes;
            mannualForm.GroupsInfo = allGroups;
            mannualForm.RegisterGroupsForRecipe();
            mannualForm.Closed += new EventHandler(mannualForm_Closed);
            mannualForm.Show();
        }

        private bool CheckCombinations(out string errMsg)
        {
            bool bValid = true;
            errMsg = "";
            foreach (Recipe recipe in recipes)
            {
                bValid = CheckCombination(recipe.SelectedGroups);
                if (!bValid)
                {
                    errMsg = string.Format("今日实验中:{0}所选组合不符合规定！", recipe.Name);
                    return false;
                }
            }
           
            return true;
        }

        private bool CheckCombination(ObservableCollection<string> selectedGroups)
        {
            BitArray bits = new BitArray(allGroups.Count);
            int curIndex = 0;
            
            for( int i = 0; i< allGroups.Count; i++)
            {
                bool bFind = false;
                foreach (string testGroup in selectedGroups)
                {
                    if (allGroups[i].Name == testGroup)
                    {
                        bFind = true;
                        break;
                    }
                }
                bits.Set(curIndex, bFind);
                curIndex++;
            }

            var result = new int[1];
            bits.CopyTo(result, 0);

            foreach (int valid in allowedCombination)
            {
                if (result[0] == valid)
                    return true;
            }
            return false;
        }

        void mannualForm_Closed(object sender, EventArgs e)
        {
            mannualForm.Closed -= new EventHandler(mannualForm_Closed);
            this.Close();
        }

 
        private void SaveSettings()
        {
            log.Info("Save settings to xml");
            string s = Utility.Serialize(allGroups);
            string sXmlPath = Utility.GetSaveFolder() + "\\Groups.xml";
            using (StreamWriter sw = new StreamWriter(sXmlPath))
            {
                sw.Write(s);
            }

            s = Utility.Serialize(recipes);
            sXmlPath = Utility.GetSaveFolder() + "\\TodayTests.xml";
            using (StreamWriter sw = new StreamWriter(sXmlPath))
            {
                sw.Write(s);
            }
            
            File.Copy(sXmlPath, Utility.GetExeFolder()+"\\TodayTests.xml",true);
          
        }

        private void SetInfo(string sText, Color color)
        {

            txtInfo.Background = Brushes.White;
            txtInfo.Text = sText;
            txtInfo.Foreground = new SolidColorBrush(color);
            
        }

        private void lstRecipe_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            UpdateSeletedGroups();
          
        }

        private void lstTestGroup_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            int selIndex = lstRecipe.SelectedIndex;
            if (selIndex == -1)
                return;

            ObservableCollection<string> selGroups = new ObservableCollection<string>();

            for(int i=0;i< allGroups.Count;i++)
            {
                if (allGroups[i].IsSelected)
                    selGroups.Add(allGroups[i].Name);
            }
            recipes[selIndex].SelectedGroups = selGroups; 
            
        }

        private void lstRecipe_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Tab)
            {
                e.Handled = true;
                return;
            }
        }

        private void lstTestGroup_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Tab)
            {
                e.Handled = true;
                return;
            }
        }

    }
}
